package com.example.testljsstarter.test.aspect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 编写注解类切面
 */
@Aspect
@Component
@SuppressWarnings({"unused"})
@Slf4j
public class LjsAspect {

    ExecutorService executorService= Executors.newSingleThreadExecutor();
    /**
     * 切点的位置
     */
    //只切注解类
   @Pointcut("@annotation(com.example.testljsstarter.test.annotaion.Ljs)")
   //切controller下面的类，只要访问comtroller都会执行切的方法
    //@Pointcut("execution(public * com.example..controller..*.*(..)))")
    public void annotationPoitCut(){
    }
    @Before("annotationPoitCut()")
    public void  beforePointCut(){
        // 此处进入到方法前  可以实现一些业务逻辑
        System.out.println("之前要做的事");

    }

    /**
     * around方法要返回值
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("annotationPoitCut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        //方法构造
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
          Method method= methodSignature.getMethod();
           String names []=   methodSignature.getParameterNames();
             Object args []= joinPoint.getArgs();

        System.out.println("参数"+ Arrays.toString(names));

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();
        String url = request.getRequestURI();
        System.out.println("请求的url"+url);
        Object obj = null;
        long begin = System.nanoTime();

        try {
            obj = joinPoint.proceed();
            long end = System.nanoTime();
            String result = JSON.toJSONString(obj);
            if ("POST".equals(request.getMethod())) {
                log.info("访问controller:{}，URL: {}，参数：{}，耗时：{}毫秒[成功]\n返回报文: {}", joinPoint.getSignature().toString(), url,
                        transferParam(joinPoint.getArgs()), (end - begin) / 1000000, result);
            }else if("GET".equals(request.getMethod())){
                log.info("访问controller:{}，URL: {}，参数：{}，耗时：{}毫秒[成功]\n返回报文: {}", joinPoint.getSignature().toString(), url,
                        transferParam(joinPoint.getArgs()), (end - begin) / 1000000, result);
            }
        } catch (Exception e) {
            long end = System.nanoTime();
            log.error("访问controller:{}，URL: {}，参数：{}，耗时：{}毫秒[业务异常]，异常原因：{}", joinPoint.getSignature().toString(), url,
                    transferParam(joinPoint.getArgs()), (end - begin) / 1000000, e.getMessage());
            throw e;
        }
        return obj;

    }
    @AfterReturning("annotationPoitCut()")
    public void doAfterReturning(JoinPoint joinPoint) {
        //之后要做的事
        System.out.println("之后要做的事");
    }

    /**
     * 转换参数
     * @param paramValues
     * @return
     */
    private String transferParam(Object[] paramValues) {
        StringBuilder sbValue = new StringBuilder();
        if (paramValues.length > 0) {
            for (int i = 0; i < paramValues.length; i++) {
                if (paramValues[i] != null) {
                    if (paramValues[i] instanceof ModelMap || paramValues[i] instanceof ServletRequest) {
                        continue;
                    }
                    sbValue.append(JSON.toJSONString(paramValues[i], SerializerFeature.IgnoreNonFieldGetter))
                            .append(",");
                }
            }
            if (StringUtils.isNotBlank(sbValue)) {
                sbValue.deleteCharAt(sbValue.length() - 1);
            }
        }
        return sbValue.toString();
    }

    @PreDestroy
    public void destory() {
        executorService.shutdown();
    }
}
